module mculib.arm.common.scb;

import std.bitmanip:bitfields;

import mculib.chip;
import mculib.arm.bus:CrtPriority,CrtFlag;


static assert(__traits(getMember, Peripherals, "SCB"), "RCC not found in Peripherals");

static
final abstract class DSCB 
{
    //pragma(LDC_global_crt_ctor, 1024)    
    pragma(crt_constructor,CrtPriority!(CrtFlag.ROOT,5))
    static this()
    {
        /// 设置默认优先级分组
        priorityGroup(PriGroup_Type.Group_4);
    }

    CPUIDInfo cpuID() const pure nothrow @nogc
    {
        return cast(CPUIDInfo)Peripherals.SCB.CPUID.rawRegister.value();
    }
    /**
    * 设置优先级分组
    */
    static void  priorityGroup(in PriGroup_Type priGroup) @property
    {
        enum VECTKEY = 0x05FA; 
        import std.bitmanip:swapEndian;

        //Peripherals.SCB.AIRCR
        auto aircr = Peripherals.SCB.AIRCR;

        ushort vkey =cast(ushort) aircr.VECTKEY;
        ushort vkey_swapped = swapEndian(vkey);

        aircr.VECTKEY = vkey_swapped; // or VECTKEY = 0x5FA
        aircr.PRIGROUP = priGroup;

        Peripherals.SCB.AIRCR = aircr;
    }

    static immutable(PriGroup_Type) priorityGroup() @property pure nothrow @nogc 
    {
        return cast(PriGroup_Type)Peripherals.SCB.AIRCR.PRIGROUP();
    }
    /**
        mcu 重置
    */
    static void resetMCU(in ResetReason op = ResetReason.resetAll) @nogc
    {
        enum VECTKEY = 0x05FA; 
        import std.bitmanip:swapEndian;
        import mculib.arm.builtins:__dsb,__nop;

        auto aircr = Peripherals.SCB.AIRCR;

        ushort vkey =cast(ushort) aircr.VECTKEY;
        ushort vkey_swapped = swapEndian(vkey);

        aircr.VECTKEY = vkey_swapped; // or VECTKEY = 0x5FA
        aircr.SYSRESETREQ = op;
        __dsb();
        Peripherals.SCB.AIRCR = aircr;
        __dsb();
        while(1) __nop();
    }

    /**
        设置中断对应的优先级
    */
    static void prioritySet()
    {

    }

}

void aa1()
{
    DSCB.priorityGroup(PriGroup_Type.Group_4);
    DSCB.resetMCU();

    auto v2 = DSCB.priorityGroup();
    auto vv = Peripherals.SCB.ICSR.VECTPENDING();
}



struct CPUIDInfo
{
    union
    {
        uint value;
        mixin(bitfields!(
            uint, "Revision",    4,         /// < 修订
            int,  "PartNo",    12,          /// < 部件号
            uint, "Constant",    4,         /// < 常量 0x0f
            uint, "Variant",    4,          /// < 变体
            uint, "Implementer", 8          /// < 实现者 0x41 = ARM
            ));
    }
    static assert(this.sizeof == uint.sizeof,"CpuInfo size is not 32 bits");
}

/// 重置标记

enum ResetReason
{
    None = 0,
    /// 重置中断
    resetInterrupt = 0b0110,
    /// 重置向量
    resetVector = 0b0101,
    /// 重置全部
    resetAll = resetInterrupt|resetVector,
}

enum PriGroup_Type
{
    Group_0 = 0x07,    ///< 0bit宽度 抢占优先级，4bit宽度 响应优先级
    Group_1 = 0x06,    ///< 1bit宽度 位抢占优先级，3bit宽度 位响应优先级
    Group_2 = 0x05,    ///< 2bit宽度 位抢占优先级，2bit宽度 位响应优先级
    Group_3 = 0x04,    ///< 3bit宽度 位抢占优先级，1bit宽度 位响应优先级
    Group_4 = 0x03,    ///< 4bit宽度 位抢占优先级，0bit宽度 位响应优先级
}


version(None):
import mculib.chip.util;

//enum bool SupportSCB = imported!"mculib.baremetal".CheckTargetCPU!("cortex-m3","cortex-m4","cortex-m7");

//static assert(SupportSCB, "This CPU does not support SCB!");


/**
* 所有scb的预定义
*/
enum SCBRegisterAddress :size_t
{
    ITM = 0xE000_0000,          ///< TIM 寄存器,

}



enum CorePeripheralAddress :size_t
{
    /// 系统控制寄存器内存地址
    SCS_Base = 0xE000_E000,
    /// TIM 寄存器内存地址
    ITM_Base = 0xE000_0000,
    /// DWT 寄存器内存地址
    DWT_Base = 0xE000_1000,
    /// TPI 寄存器内存地址
    TPI_Base = 0xE004_0000,
    /// CoreDebug 寄存器内存地址
    CoreDebug_Base = 0xE000_EDF0,
    /// SysTick 寄存器内存地址 0xe000_e010 ~ 0xe000_e01f
    SysTick_Base = SCS_Base + 0x0010,
    /// NVIC 寄存器内存地址 0xe000_e100 ~ 0xe000_e4ef
    NVIC_Base = SCS_Base + 0x0100,
    /// SCB 寄存器内存地址, 
    SCB_Base = SCS_Base + 0x0D00,
    /// FPU 寄存器内存地址, 0xe000_ed88 ~ 0xe000_ed8b
    FPU_Base = SCS_Base + 0x0F30,
    FPU_CPACR = SCB_Base + 0x88,
    /// MPU 寄存器内存地址
    MPU_Base = SCS_Base + 0x0D90,
}

